package com.wyman.beans.factory.support;

import com.wyman.beans.BeanException;
import com.wyman.beans.factory.DisposableBean;
import com.wyman.beans.factory.ObjectFactory;
import com.wyman.beans.factory.config.SingletonBeanRegistry;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author 李伟民
 * @Description  存放容器创建出来的单例对象
 * @DateTime 2024/11/25 01:46
 */
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    //12.14 后面空的对象就返回这个
    public static final Object NULL_OBJECT = new Object();

    private final ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap<>();

    private final Map<String, DisposableBean> disposableBeanMap = new HashMap<>();


    //二级缓存 在多组依赖中会用到 存放未完全初始化的对象
    protected final Map<String,Object> earlySingletonObjects = new HashMap<>();

    //三级缓存 放创建代理的类
    protected final Map<String, ObjectFactory> singletonFactories = new HashMap<>();


    @Override
    public Object getSingleton(String beanName) {

        Object singletonObject = singletonObjects.get(beanName);

        if(singletonObject==null){

            singletonObject = earlySingletonObjects.get(beanName);

            if(singletonObject==null){

                ObjectFactory factory = singletonFactories.get(beanName);

                if(factory!=null){

                    singletonObject =  factory.getObject();

                    singletonFactories.remove(beanName);

                    earlySingletonObjects.put(beanName,singletonObject);
                }

            }
        }
        return singletonObject;

    }


    protected void addSingleton(String beanName,Object singletonObject){
        singletonObjects.put(beanName,singletonObject);
    }

    public void registerDisposableBean(String beanName, DisposableBean bean){
        disposableBeanMap.put(beanName,bean);
    }

    @Override
    public void destroySingletons() {
        Set<String> strings = disposableBeanMap.keySet();
        Object[] disposableBeanNames = strings.toArray();

        for(int i=0;i<disposableBeanNames.length;i++){
            Object beanName = disposableBeanNames[i];
            DisposableBean disposableBean = disposableBeanMap.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeanException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
            }

        }

    }

    //三级缓存 新增注册单例对象方法 供给广播器注册
    public void registerSingleton(String beanName,Object beanObject){
        singletonObjects.put(beanName,beanObject);
        earlySingletonObjects.remove(beanName);
        singletonFactories.remove(beanName);
    }


    //三级缓存
    public void addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory){
        if(!this.singletonFactories.containsKey(beanName)){
            earlySingletonObjects.remove(beanName);
            singletonFactories.put(beanName,singletonFactory);
        }
    }

}
